﻿using UnityEngine;
using System.Collections;

class AnimationHelper
{
    private Counter m_PlayingAnimations = new Counter();

    public bool isIdle { get { return m_PlayingAnimations.IsZero(); } }

    // Coroutine based linear move from initial position to target
    public IEnumerator LinearMove(Transform entity, Vector3 target, float time)
    {
        m_PlayingAnimations.Increment();
        Vector3 initialPosition = entity.position;
        float amount = 0.5f;
        while (entity.position != target)
        {
            amount += Time.deltaTime;
            entity.position = Vector3.Lerp(initialPosition, target, amount / time);
            yield return new WaitForEndOfFrame();
        }
        m_PlayingAnimations.Decrement();
    }

    // Coroutine based spring move from initial position to target
    public IEnumerator SpringMove(Transform entity, Vector3 target, float time, float strength)
    {
        m_PlayingAnimations.Increment();
        float treshold = Vector3.Distance(entity.position, target) * 0.01f;
        Vector3 initialPosition = entity.position;
        float amount = 0.0f;
        while (treshold < Vector3.Distance(entity.position, target) && amount < time)
        {
            amount += Time.deltaTime;
            entity.position = NGUIMath.SpringLerp(initialPosition, target, strength, amount / time);
            yield return new WaitForEndOfFrame();
        }
        entity.position = target;
        m_PlayingAnimations.Decrement();
    }

    // Pseudo-circular movement due to zero nowledge in math
    public IEnumerator CircularMove(Transform entity, Vector3 target, float time, bool upwards  = true)
    {
        m_PlayingAnimations.Increment();
        Vector3 initialPosition = entity.position;
        float amount = 0.0f;
        float actualAmount = 0.0f;
        float radius = Vector3.Distance(initialPosition, target) * 0.5f * (upwards ? 1 : -1);
        while (actualAmount < 0.99f && amount < time)
        {
            amount += Time.deltaTime;
            actualAmount = amount / time;
            entity.position = Vector3.Lerp(initialPosition, target, actualAmount);

            float deltaZ = actualAmount < 0.5f ? Mathf.Lerp(0, radius,  actualAmount * 2.0f) : Mathf.Lerp(radius, 0, actualAmount * 2.0f - 1.0f);
            entity.position = new Vector3(entity.position.x, entity.position.y, entity.position.z + deltaZ); 
            yield return new WaitForEndOfFrame();
        }
        entity.position = target;
        m_PlayingAnimations.Decrement();
    }

    public IEnumerator ShrinkGrow(Transform entity, float time, bool shrink = true)
    {
        m_PlayingAnimations.Increment();
        float amount = 0.0f;
        Vector3 initialScale = entity.localScale;
        do
        {
            amount += Time.deltaTime;
            float actualAmount = amount / time;
            actualAmount = shrink ? actualAmount : 1 - actualAmount;
            entity.localScale = new Vector3(Mathf.Lerp(initialScale.x, 0, actualAmount), Mathf.Lerp(initialScale.y, 0, actualAmount), Mathf.Lerp(initialScale.z, 0, actualAmount));
            yield return new WaitForEndOfFrame();
        } while (amount < time);
        entity.localScale = initialScale;
        m_PlayingAnimations.Decrement();
    }
}
